package com.woniuxy.book.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.book.entity.*;
import com.woniuxy.book.exception.orderinfo.OrderInfoException;
import com.woniuxy.book.exception.orderinfo.OrderInfoExceptionCode;
import com.woniuxy.book.exception.orderrefund.OrderRefundException;
import com.woniuxy.book.exception.orderrefund.OrderRefundExceptionCode;
import com.woniuxy.book.mapper.BookInfoMapper;
import com.woniuxy.book.mapper.OrderInfoMapper;
import com.woniuxy.book.mapper.OrderItemMapper;
import com.woniuxy.book.mapper.OrderRefundMapper;
import com.woniuxy.book.param.orderrefund.ApplyNoPassParam;
import com.woniuxy.book.param.orderrefund.ApplyRefundParam;
import com.woniuxy.book.param.orderrefund.RefundParam;
import com.woniuxy.book.service.OrderRefundService;
import com.woniuxy.book.util.StateData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class OrderRefundServiceImpl implements OrderRefundService {

    @Resource
    private OrderRefundMapper orderRefundMapper;
    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private OrderItemMapper orderItemMapper;

    @Resource
    private BookInfoMapper bookInfoMapper;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    @Transactional
    public void applyRefund(ApplyRefundParam param) throws Exception {
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_num",param.getOrderId());
        queryWrapper.eq("user_id",param.getUserId());
        OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);
        if (orderInfo==null) {
            throw new OrderInfoException(OrderInfoExceptionCode.ORDER_INFO_EXCEPTION_ORDER_NOTEXITS);
        }
        OrderRefund orderRefund = BeanUtil.toBean(param, OrderRefund.class);
        //使用雪花算法生成退款订单编号
        String refundId = new Snowflake(1, 1).nextIdStr();
        QueryWrapper<OrderItem> orderItemQueryWrapper = new QueryWrapper<>();
        orderItemQueryWrapper.eq("order_id",orderInfo.getOrderNum());
        List<OrderItem> orderItems = orderItemMapper.selectList(orderItemQueryWrapper);
        double total = 0;
        for (OrderItem orderItem : orderItems) {
            Integer bookId = orderItem.getBookId();
            Integer number = orderItem.getBookCont();
            BookInfo bookInfo = bookInfoMapper.selectById(bookId);
            if (bookInfo == null) {
                throw new Exception("书籍信息不存在");
            }
            //计算单种商品总金额
            Double price = Double.parseDouble(bookInfo.getBookPrice().multiply(new BigDecimal(number)).toString());
            total+=price;
        }
        orderRefund.setRefundId(refundId);
        orderRefund.setRefundMoney(new BigDecimal(total));
        orderRefund.setRefundState(StateData.ORDER_REFUND_PENDING);
        orderInfo.setOrderState(StateData.ORDER_STATE_APPLYREFUND);
        orderInfoMapper.updateById(orderInfo);
        orderRefundMapper.insert(orderRefund);
    }

    @Override
    public void refund(RefundParam param) {
        OrderRefund orderRefund = orderRefundMapper.selectById(param.getRefundId());
        //若该退款订单不存在抛出异常

        if (orderRefund==null) {
            throw new OrderRefundException(OrderRefundExceptionCode.ORDER_REFUND_EXCEPTION_APPLYREFUND_NOTEXITS);
        }
        if (!orderRefund.getOrderId().equals(param.getOrderId())) {
            throw new OrderRefundException(OrderRefundExceptionCode.ORDER_REFUND_EXCEPTION_REFUNDORDER_NOTEXITS);
        }
        if (orderRefund.getRefundState()!= StateData.ORDER_REFUND_PENDING) {
            throw new OrderRefundException(OrderRefundExceptionCode.ORDER_REFUND_EXCEPTION_REFUNDSTATE_ERRO);
        }
        //将退款所需要的参数保存到refund-queue这个队列中
        Map<String, Object> refundParam = new HashMap<>();
        refundParam.put("orderId",param.getOrderId());
        refundParam.put("refundMoney",orderRefund.getRefundMoney());
        refundParam.put("refundReason",orderRefund.getRefundReason());
        refundParam.put("refundId",orderRefund.getRefundId());
        rabbitTemplate.convertAndSend("refund-queue",refundParam);
    }

    @Override
    public PageInfo selectRefundOrders(Integer pageNum, Integer pageSize, Integer refundState) {
        QueryWrapper<OrderRefund> wrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(refundState)) {
            wrapper.eq("refund_state", refundState);
        }
        Page<OrderRefund> page = new Page<OrderRefund>(pageNum == null ? 1 : pageNum, pageSize == null ? 5 : pageSize);
        orderRefundMapper.selectPage(page, wrapper);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(page.getRecords());
        return pageInfo;
    }

    @Override
    public PageInfo searchRefundOrder(Integer pageNum, Integer pageSize, Integer userId) {
        QueryWrapper<OrderRefund> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        Page<OrderRefund> page = new Page<OrderRefund>(pageNum == null ? 1 : pageNum, pageSize == null ? 5 : pageSize);
        orderRefundMapper.selectPage(page, wrapper);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(page.getRecords());
        return pageInfo;
    }

    @Override
    public void applyNoPass(ApplyNoPassParam param) {
        OrderRefund orderRefund = orderRefundMapper.selectById(param.getRefundId());
        if (orderRefund==null) {
            throw new OrderRefundException(OrderRefundExceptionCode.ORDER_REFUND_EXCEPTION_APPLYREFUND_NOTEXITS);
        }
        orderRefund.setRefundState(StateData.ORDER_REFUND_REJECTED);
        orderRefund.setRejectReason(param.getReason());
        OrderInfo orderInfo = orderInfoMapper.selectById(orderRefund.getOrderId());
        if (orderInfo==null) {
            throw new OrderInfoException(OrderInfoExceptionCode.ORDER_INFO_EXCEPTION_ORDER_NOTEXITS);
        }
        orderInfo.setOrderState(StateData.ORDER_STATE_REFUNDNOPASS);
        orderRefundMapper.updateById(orderRefund);
        orderInfoMapper.updateById(orderInfo);
    }

    @Override
    public void applyRefundAgain(String refundId, Integer userId) {
        OrderRefund orderRefund = orderRefundMapper.selectById(refundId);
        if (orderRefund==null) {
            throw new OrderRefundException(OrderRefundExceptionCode.ORDER_REFUND_EXCEPTION_APPLYREFUND_NOTEXITS);
        }
        if (orderRefund.getUserId()!=userId) {
            throw new OrderRefundException(OrderRefundExceptionCode.ORDER_REFUND_EXCEPTION_REFUNDORDER_NOTYOUR);
        }
        OrderInfo orderInfo = orderInfoMapper.selectById(orderRefund.getOrderId());
        orderRefund.setRefundState(StateData.ORDER_REFUND_PENDING);
        orderRefund.setRejectReason("");
        orderInfo.setOrderState(StateData.ORDER_STATE_APPLYREFUND);
        orderRefundMapper.updateById(orderRefund);
        orderInfoMapper.updateById(orderInfo);
    }
}
